home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Controls / Visual Basic Controls.iso / vbcontrol / spchauto / data1.cab / Samples / Visual_C++ / Editor / SpellTxt.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-07-16  |  27.7 KB  |  935 lines

  1. /********************************************************************
  2.                       SPELLTXT.CPP
  3.  
  4.   @DOC    SPELLTXT
  5.   @MODULE SPELLTXT - CEditView Spelling checker |
  6.  
  7.   SPELL CHECKER RULES:  <nl>
  8.      - text is considered to be a word if it is not longer than 63 letters
  9.  
  10.   PROCEDURE:            <nl>
  11.      Spelling starts with <mf TSpelText::StartSpell>
  12.      If the word which is not in dictionary occures there, than dialog
  13.      is being started and suggestion is being offered.
  14.      Spelling continues in terms of <mf TSpellText::FindNextNotExistWord>
  15.      function which returns TRUE if it finds word that doesn't exist
  16.      in dictionary. That word is also in m_szString buffer,
  17.      and m_WordBegPos marks  its beginning and m_WordEndPos marks its end.
  18.      After that suggestion for that nonexisting word is being asked.
  19.      We continue from m_lEndWord + 1 word in FindNextNotExistWord()
  20.      function.
  21.  
  22.   PUBLIC MEMBER FUNCTIONS:
  23.      <mf TSpellText::TSpellText>                      <nl>
  24.      <mf TSpellText::StartSpell>                      <nl>
  25.      <mf TSpellText::SelectNotExistSpellWord>         <nl>
  26.      <mf TSpellText::FindNextNotExistWord>            <nl>
  27.      <mf TSpellText::FindNotExistInBoundary>          <nl>
  28.      <mf TSpellText::ReplaceWord>                     <nl>
  29.  
  30.   You should also see TSpellText base class: TSpellCheck (defined
  31.   in SPELL.CPP)
  32.  
  33.   Spelling of text (only modul which depends of program)
  34. ********************************************************************/
  35.  
  36. #include "stdafx.h"
  37. #pragma hdrstop
  38.  
  39. #include <stdio.h>
  40. #include "resource.h"
  41. #include "spelltxt.h"
  42.  
  43.  
  44. /********************************************************************
  45.                          TSpellText
  46.  
  47.   Class for spelling - inhereted from TSpellChecker
  48. ********************************************************************/
  49.  
  50.  
  51.  
  52. /*-------------------------------------------------------------------
  53.                        TSpellText::TSpellText
  54. -------------------------------------------------------------------*/
  55.  
  56. TSpellText::TSpellText(CEditView *pEditView, TSpellingChecker *pSpellChecker)
  57. {
  58.    m_pEditView   = pEditView;
  59.    m_pSpellChecker = pSpellChecker;
  60. }
  61.  
  62. /*-------------------------------------------------------------------
  63.                   TSpellText - destructor
  64. -------------------------------------------------------------------*/
  65.  
  66. TSpellText::~TSpellText()
  67. {
  68. }
  69.  
  70. /*-------------------------------------------------------------------
  71.                       StartSpell
  72.  @mfunc
  73.  
  74.    Start of spelling, showing of dialog...
  75.  
  76.    WORK EXPLANATION: <nl>
  77.      Starting position from which spelling starts is being determined
  78.      and than first word is being searched from that position.
  79.  
  80.      If there is no word from to position we go Out.
  81.      If there is word from to position, than loop is being started.
  82.       LOOP
  83.          It is being checked whether word exists in dictionary.
  84.             If there IS word than we go to next word or we go out of loop
  85.             (if we have reached the end or if there are no more words).
  86.             If there IS NO word than we go out of loop.
  87.       DIALOG IS BEING STARTED
  88.          This pointer is being forwarded into dialog, and searching process
  89.          is being continued there in the same way as till now.
  90.  
  91.  @rdesc
  92.     Returns TRUE if the message "Spelling check is complete" should be
  93.     displayed (checking string was complete and dialog box was never
  94.     displayed - actually this means that string are correct).
  95. -------------------------------------------------------------------*/
  96.  
  97. BOOL TSpellText::StartSpell(int nStartPos, int nEndPos)
  98. {
  99.    HCURSOR hOldCursor;
  100.    BOOL    fFoundErrorWords;
  101.    BOOL    fReturn;
  102.  
  103.    if(nStartPos > nEndPos)
  104.    {
  105.       m_SpellBegPos = nEndPos;
  106.       m_SpellEndPos = nStartPos;
  107.    }
  108.    else {
  109.       m_SpellBegPos = nStartPos;
  110.       m_SpellEndPos = nEndPos;
  111.    }
  112.  
  113.    if(m_SpellBegPos >= m_SpellEndPos)
  114.    {
  115.       // if there is nothing to spell
  116.       return TRUE;
  117.    }
  118.  
  119.    // Set the cursor to the hourglass and save the previous cursor.
  120.    hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  121.  
  122.    m_WordBegPos = m_SpellBegPos;
  123.    m_WordEndPos = m_SpellEndPos;
  124.  
  125.    fFoundErrorWords = FindNotExistInBoundary();
  126.  
  127.    //Restore the previous cursor.
  128.    SetCursor(hOldCursor);
  129.  
  130.    // here goes the message which notifies that spelling is over
  131.  
  132.    if(fFoundErrorWords == TRUE)
  133.    {
  134.       // this means we have found the word which doesn't exist neither in
  135.       // spell nor in change all buffer (which is empty anyway because class
  136.       // has just been created)
  137.       TSpellDlg SpellDlg(m_pEditView, this);
  138.  
  139.       if(SpellDlg.DoModal() == IDOK)
  140.          fReturn = TRUE;
  141.       else
  142.          fReturn = FALSE;
  143.    }
  144.    else
  145.    {
  146.       fReturn = TRUE;
  147.    }
  148.  
  149.    return fReturn;
  150. }
  151.  
  152. /*-------------------------------------------------------------------
  153.                    SelectNotExistSpellWord
  154.  @mfunc
  155.  
  156.   Selects word which is from m_lBeginWord to m_lEndWord in DocText object,
  157.   and moves screen so that word can be seen on it.
  158. -------------------------------------------------------------------*/
  159.  
  160. void TSpellText::SelectNotExistSpellWord()
  161. {
  162.    m_pEditView->GetEditCtrl().SetSel(m_WordBegPos, m_WordEndPos);
  163. }
  164.  
  165. /*-------------------------------------------------------------------
  166.                 FindNextNotExistWord
  167.  @mfunc
  168.  
  169.    Starting from m_WordEndPos position we search for the next word
  170.    which is not in dictionary or in changeAll buffer.
  171.  
  172.  @rdesc
  173.    TRUE  if we have found the word which doesn't exist in dictionary.     <nl>
  174.    FALSE if we haven't found the word which doesn't exist in dictionary.  <nl>
  175.  
  176. -------------------------------------------------------------------*/
  177.  
  178. BOOL TSpellText::FindNextNotExistWord()
  179. {
  180.    m_WordBegPos = m_WordEndPos;
  181.    m_WordEndPos = m_SpellEndPos;
  182.  
  183.    if(m_WordBegPos >= m_WordEndPos)
  184.    {
  185.       return FALSE;
  186.    }
  187.    return FindNotExistInBoundary();
  188. }
  189.  
  190. /*-------------------------------------------------------------------
  191.                  FindNotExistInBoundary
  192.  @mfunc
  193.  
  194.    Finds nonexisting word within already prepared borders:
  195.    m_WordBegPos and m_WordEndPos
  196.  
  197.    If the word which has been found here isn't in dictionary but
  198.    in changeAll buffer than lets replace it here with that word from
  199.    changeAll buffer.
  200.  
  201.  @rdesc
  202.    TRUE  if we have found the word which doesn't exist in dictionary.    <nl>
  203.    FALSE if we haven't found the word which doesn't exist in dictionary. <nl>
  204. -------------------------------------------------------------------*/
  205.  
  206. BOOL TSpellText::FindNotExistInBoundary()
  207. {
  208.    while(TRUE)
  209.    {
  210.       const char *pszWord; // pointer to the beginning of the word
  211.  
  212.       if(GetFirstWordPos(m_WordBegPos, TRUE, TRUE, FALSE,
  213.          &m_WordBegPos, &m_WordEndPos) == FALSE)
  214.       {
  215.          return FALSE;
  216.       }
  217.  
  218.       // if word has been found outside of selection
  219.       if(m_WordBegPos > m_SpellEndPos)
  220.       {
  221.          return FALSE;
  222.       }
  223.  
  224.       // WordPos contains beginning of the word
  225.  
  226.       // Get text after m_WordBegPos
  227.       // Because we use CEdit control we can get only complete text or
  228.       // line, so we will get line and point pszWord to the text of the word
  229.       char *pszLine;
  230.       int nLineIdx;
  231.       CEdit & EditCtrl = m_pEditView->GetEditCtrl();
  232.  
  233.       nLineIdx = EditCtrl.LineFromChar(m_WordBegPos);
  234.       pszLine = (char *)malloc(EditCtrl.LineLength(nLineIdx) + 1 + 8);
  235.       memset(pszLine, 0, EditCtrl.LineLength(nLineIdx) + 1 + 8);
  236.       EditCtrl.GetLine(nLineIdx, pszLine, EditCtrl.LineLength(nLineIdx) + 1);
  237.  
  238.       pszWord = pszLine + (m_WordBegPos - EditCtrl.LineIndex(nLineIdx));
  239.  
  240.       // Whether word starts with '_'
  241.       if(*pszWord == '_')
  242.       {
  243.          m_WordBegPos = m_WordEndPos;
  244.          m_WordEndPos = m_SpellEndPos;
  245.          if(m_WordBegPos >= m_SpellEndPos)
  246.          {
  247.             free(pszLine);
  248.             return FALSE;
  249.          }
  250.          continue;
  251.       }
  252.  
  253.       // we are ignoring words this long
  254.       if(m_WordEndPos - m_WordBegPos > 63)
  255.       {
  256.          // we are ignoring words this long
  257.          m_WordBegPos = m_WordEndPos;
  258.          m_WordEndPos = m_SpellEndPos;
  259.          if(m_WordBegPos >= m_SpellEndPos)
  260.          {
  261.             free(pszLine);
  262.             return FALSE;
  263.          }
  264.          continue;
  265.       }
  266.  
  267.       // Taking of words
  268.       m_szString[0] = 0;
  269.       strncat(m_szString, pszWord, m_WordEndPos - m_WordBegPos);
  270.  
  271.       // whether words consists of all numerals
  272.       if(isdigit((unsigned char)*m_szString))
  273.       {
  274.          char  *psz    = m_szString;
  275.          short fAllNum = TRUE;
  276.  
  277.          while(*psz)
  278.          {
  279.             if(isdigit((unsigned char)*psz) == FALSE) {
  280.                fAllNum = FALSE;
  281.                break;
  282.             }
  283.             psz++;
  284.          }
  285.  
  286.          if(fAllNum) {
  287.             m_WordBegPos = m_WordEndPos;
  288.             m_WordEndPos = m_SpellEndPos;
  289.             if(m_WordBegPos >= m_SpellEndPos)
  290.             {
  291.                free(pszLine);
  292.                return FALSE;
  293.             }
  294.             continue;
  295.          }
  296.       }
  297.  
  298.       // IgnoreWordsInUppercase
  299.       if(m_pSpellChecker->GetIgnoreWordsInUppercase())
  300.       {
  301.          char  *psz = m_szString;
  302.          short fAllUpper = TRUE;
  303.  
  304.          while(*psz) {
  305.             if(m_pSpellChecker->IsCharUpper(*psz) == 0)
  306.             {
  307.                fAllUpper = FALSE;
  308.                break;
  309.             }
  310.             psz++;
  311.          }
  312.          if(fAllUpper)
  313.          {
  314.             m_WordBegPos = m_WordEndPos;
  315.             m_WordEndPos = m_SpellEndPos;
  316.             if(m_WordBegPos >= m_SpellEndPos)
  317.             {
  318.                free(pszLine);
  319.                return FALSE;
  320.             }
  321.             continue;
  322.          }
  323.       }
  324.  
  325.       // IgnoreWordWithNumbers
  326.       if(m_pSpellChecker->GetIgnoreWordsWithNumbers())
  327.       {
  328.          char  *psz = m_szString;
  329.          short fNumber = FALSE;
  330.  
  331.          while(*psz) {
  332.             if(isdigit((unsigned char)*psz) != 0) {
  333.                fNumber = TRUE;
  334.                break;
  335.             }
  336.             psz++;
  337.          }
  338.          if(fNumber) {
  339.             m_WordBegPos = m_WordEndPos;
  340.             m_WordEndPos = m_SpellEndPos;
  341.             if(m_WordBegPos >= m_SpellEndPos)
  342.             {
  343.                free(pszLine);
  344.                return FALSE;
  345.             }
  346.             continue;
  347.          }
  348.       }
  349.  
  350.       if(m_pSpellChecker->IsWordExist(m_szString) == FALSE)
  351.       {
  352.          // This word doesn't exist in dictionary so we must investigate
  353.          // whether it exists in changAll words buffer
  354.          // If it is than we replace it here and we continue. If it isn't
  355.          // than dialog and suggestion must be shown to user.
  356.  
  357.          CString strReplace;
  358.  
  359.          strReplace = m_pSpellChecker->GetReplacement(m_szString);
  360.          if(strReplace.IsEmpty() == FALSE)
  361.          {
  362.            // Than we have found that replacement for this word exists
  363.            // so lets replace it with pszReplace word.
  364.  
  365.            ReplaceWord((LPCTSTR)strReplace);
  366.            m_WordEndPos = m_WordBegPos + strlen((LPCTSTR)strReplace);
  367.          }
  368.          else
  369.          {
  370.             // we have found the word which doesn't exist in dictionary
  371.             free(pszLine);
  372.             return TRUE;
  373.          }
  374.       }
  375.  
  376.       m_WordBegPos = m_WordEndPos;
  377.       m_WordEndPos = m_SpellEndPos;
  378.       if(m_WordBegPos >= m_SpellEndPos)
  379.       {
  380.          free(pszLine);
  381.          return FALSE;
  382.       }
  383.    }
  384. }
  385.  
  386.  
  387. /*-------------------------------------------------------------------
  388.                     ReplaceWord
  389.  @mfunc
  390.  
  391.    Replaces current word (for which spell has found that it doesn't
  392.    exist in dictionary) with pszWordForReplace which was sent.
  393. -------------------------------------------------------------------*/
  394.  
  395. void TSpellText::ReplaceWord(const char *pszWordForReplace)
  396. {
  397.    if(pszWordForReplace == NULL)
  398.    {
  399.       return;
  400.    }
  401.  
  402.    CEdit &EditCtrl = m_pEditView->GetEditCtrl();
  403.    EditCtrl.SetSel(m_WordEndPos, m_WordBegPos, TRUE);
  404.    EditCtrl.ReplaceSel(pszWordForReplace);
  405.  
  406.    m_SpellEndPos += strlen(pszWordForReplace) - (m_WordEndPos - m_WordBegPos);
  407.    m_WordEndPos += strlen(pszWordForReplace) - (m_WordEndPos - m_WordBegPos);
  408. }
  409.  
  410.  
  411.  
  412. /*-------------------------------------------------------------------
  413.                    GetFirstWordPos
  414.  @mfunc
  415.  
  416.   Finds first word located behind pos position
  417.  
  418.   @parm pos                - position
  419.   @parm fInclBackPos       -if it is possible to return the word located in
  420.                             front of pos. E.g. if pos is within a word
  421.                             is it possible to return position on that word
  422.                             (lower than pos).
  423.   @parm fInclSingleQuote   -if single quote (') can be found within word
  424.                             (not at the end or at the beginning of word
  425.                             but only within)
  426.   @parm fIgnoreTexKeywords -ignoring of UNIX Tex Keyworda i.e. of all words
  427.                             starting with '\' (e.g.  \doc)
  428.  
  429.   @parm pWordStartPos      -pointer to int in which is written position
  430.                             of the beginning of the word
  431.   @parm pWordEndPos        -pointer to int in which is written position
  432.                             of the end of the word(position of the first
  433.                             letter behind the word)
  434.  
  435.  @rdesc
  436.     Returns FALSE if the word hasn't been found.
  437.  
  438.  @comm
  439.     Since there can not be tabulators within word, its length
  440.     can be determined as pWordEndPos - pWordStartPos
  441. -------------------------------------------------------------------*/
  442.  
  443. int TSpellText::GetFirstWordPos(int pos, BOOL fInclBackPos, BOOL fInclSingleQuote,
  444.                             BOOL fIgnoreTexKeywords, int *pWordStartPos, int *pWordEndPos)
  445. {
  446.    const char *psz;
  447.    const char *pszStart;
  448.  
  449.    CEdit& EditCtrl = m_pEditView->GetEditCtrl();
  450.  
  451.    pszStart = m_pEditView->LockBuffer();
  452.  
  453.    psz = pszStart + pos;
  454.  
  455.  
  456.    if(m_pSpellChecker->IsCharAlpha(*psz))
  457.    {
  458.       // if this is the first letter in string or if there is no letter
  459.       // preceding it
  460.       if(psz == pszStart || (psz != pszStart && m_pSpellChecker->IsCharAlpha(*(psz-1)) == FALSE))
  461.       {
  462.          if(psz == pszStart || *(psz-1) != '\\')
  463.          {
  464.             *pWordStartPos = pos;
  465.             *pWordEndPos = pos + 1;
  466.             psz++;
  467.             if(fInclSingleQuote)
  468.             {
  469.                while(m_pSpellChecker->IsCharAlpha(*psz) || *psz == '\'' || isdigit((unsigned char)*psz))
  470.                {
  471.                   psz++;
  472.                   (*pWordEndPos)++;
  473.                }
  474.  
  475.                if(psz != pszStart && *(psz-1) == '\'')
  476.                   (*pWordEndPos)--;
  477.             }
  478.             else
  479.             {
  480.                while(m_pSpellChecker->IsCharAlpha(*psz) || isdigit((unsigned char)*psz))
  481.                {
  482.                   psz++;
  483.                   (*pWordEndPos)++;
  484.                }
  485.             }
  486.             m_pEditView->UnlockBuffer();
  487.             return TRUE;
  488.          }
  489.       }
  490.       else
  491.       {
  492.          // if it is allowed we go back to the beginning of word
  493.          // (only for first line)
  494.          if(fInclBackPos)
  495.          {
  496.             while(psz != pszStart)
  497.             {
  498.                if(m_pSpellChecker->IsCharAlpha(*(psz-1)) == FALSE)
  499.                {
  500.                   break;
  501.                }
  502.                pos--;
  503.                psz--;
  504.             }
  505.             if(psz == pszStart || *(psz-1) != '\\')
  506.             {
  507.                *pWordStartPos = pos;
  508.                *pWordEndPos = pos + 1;
  509.                psz++;
  510.                if(fInclSingleQuote)
  511.                {
  512.                   while(m_pSpellChecker->IsCharAlpha(*psz) || *psz == '\'')
  513.                   {
  514.                      psz++;
  515.                      (*pWordEndPos)++;
  516.                   }
  517.                   if(psz != pszStart && *(psz-1) == '\'')
  518.                      (*pWordEndPos)--;
  519.                }
  520.                else {
  521.                   while(m_pSpellChecker->IsCharAlpha(*psz)) {
  522.                      psz++;
  523.                      (*pWordEndPos)++;
  524.                   }
  525.                }
  526.                m_pEditView->UnlockBuffer();
  527.                return TRUE;
  528.             }
  529.          }
  530.       }
  531.  
  532.       while(m_pSpellChecker->IsCharAlpha(*psz))
  533.       {
  534.          psz++;
  535.       }
  536.    }
  537.  
  538.    while(TRUE)
  539.    {
  540.       while(*psz != 0 && m_pSpellChecker->IsCharAlpha(*psz) == FALSE)
  541.          psz++;
  542.       // pos is lost
  543.       if(m_pSpellChecker->IsCharAlpha(*psz) && (psz == pszStart || *(psz-1) != '\\'))
  544.       {
  545.          *pWordStartPos = *pWordEndPos = psz - pszStart;
  546.          (*pWordEndPos)++;
  547.          psz++;
  548.          if(fInclSingleQuote)
  549.          {
  550.             while(m_pSpellChecker->IsCharAlpha(*psz) || *psz == '\'')
  551.             {
  552.                psz++;
  553.                (*pWordEndPos)++;
  554.             }
  555.             if(psz != pszStart && *(psz-1) == '\'')
  556.                (*pWordEndPos)--;
  557.          }
  558.          else
  559.          {
  560.             while(m_pSpellChecker->IsCharAlpha(*psz))
  561.             {
  562.                psz++;
  563.                (*pWordEndPos)++;
  564.             }
  565.          }
  566.          m_pEditView->UnlockBuffer();
  567.          return TRUE;
  568.       }
  569.       break;
  570.    }
  571.    m_pEditView->UnlockBuffer();
  572.    return FALSE;
  573. }
  574.  
  575.  
  576.  
  577. /*******************************************************************
  578.                        TSpellDlg
  579.  
  580.   Dialog for spelling
  581. *******************************************************************/
  582.  
  583. #define IDC_NOT_IN_DIC    101
  584. #define IDC_COMBO_SUGGEST 102
  585. #define IDC_BTN_IGNOR     103
  586. #define IDC_BTN_IGNORALL  104
  587. #define IDC_BTN_CHANGE    105
  588. #define IDC_BTN_CHANGEALL 106
  589. #define IDC_BTN_ADD       107
  590. #define IDC_BTN_SUGGEST   108
  591. #define IDC_BTN_OPTIONS   109
  592.  
  593.  
  594. BEGIN_MESSAGE_MAP(TSpellDlg, CDialog)
  595.    ON_CBN_EDITCHANGE(IDC_COMBO_SUGGEST, CBEditChange_Suggest)
  596.    ON_BN_CLICKED(IDC_BTN_IGNOR,         CmIgnore)
  597.    ON_BN_CLICKED(IDC_BTN_IGNORALL,      CmIgnoreAll)
  598.    ON_BN_CLICKED(IDC_BTN_CHANGE,        CmChange)
  599.    ON_BN_CLICKED(IDC_BTN_CHANGEALL,     CmChangeAll)
  600.    ON_BN_CLICKED(IDC_BTN_SUGGEST,       CmSuggest)
  601.    ON_BN_CLICKED(IDC_BTN_ADD,           CmAdd)
  602.    ON_BN_CLICKED(IDC_BTN_OPTIONS,       CmOptions)
  603.    //EV_CHILD_NOTIFY(IDCANCEL, BN_CLICKED, CmCancel),
  604. END_MESSAGE_MAP()
  605.  
  606.  
  607. TSpellDlg::TSpellDlg(CWnd * pParent, TSpellText *pSpellDoc)
  608.    : CDialog("Spell", pParent)
  609. {
  610.    m_pSpellDocument = pSpellDoc;
  611. }
  612.  
  613.  
  614. BOOL TSpellDlg::OnInitDialog()
  615. {
  616.     CDialog::OnInitDialog();
  617.    //CenterDialog(m_hWnd, FALSE);
  618.  
  619.    SetDlgItemText(IDC_NOT_IN_DIC, m_pSpellDocument->m_szString);
  620.    m_pSpellDocument->SelectNotExistSpellWord();
  621.  
  622.    if(m_pSpellDocument->m_pSpellChecker->GetAlwaysSuggest())
  623.    {
  624.       BOOL fSuggestions = FALSE;
  625.  
  626.         // List of suggestions for word which has not been found is
  627.       // being filled now
  628.       for(int i = 0; i < 10; i++)
  629.       {
  630.          CString strSuggestion = m_pSpellDocument->m_pSpellChecker->GetSuggestion(m_pSpellDocument->m_szString, i);
  631.  
  632.          if(strSuggestion.GetLength() > 0)
  633.          {
  634.             SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)(LPCTSTR)strSuggestion);
  635.             fSuggestions = TRUE;
  636.          }
  637.          else
  638.             break;
  639.       }
  640.       if(fSuggestions)
  641.       {
  642.            SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_SETCURSEL, 0, 0);
  643.       }
  644.       else
  645.       {
  646.          char szBuf[40];
  647.  
  648.          LoadString(AfxGetResourceHandle(), IDS_WE_SPELL_NOSUGGESTION, szBuf, sizeof(szBuf));
  649.          SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)szBuf);
  650.       }
  651.       ::EnableWindow(GetDlgItem(IDC_BTN_SUGGEST)->GetSafeHwnd(), FALSE);
  652.    }
  653.    else
  654.    {
  655.       SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_RESETCONTENT, 0, 0L);
  656.       SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)"");
  657.       ::EnableWindow(GetDlgItem(IDC_BTN_SUGGEST)->GetSafeHwnd(), FALSE);
  658.    }
  659.    SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_LIMITTEXT, 31, 0L);
  660.  
  661.    return TRUE;
  662. }
  663.  
  664.  
  665. void TSpellDlg::CBEditChange_Suggest()
  666. {
  667.    char szBuf[32];
  668.  
  669.    GetDlgItemText(IDC_COMBO_SUGGEST, szBuf, sizeof(szBuf));
  670.    // enabling Suggest only if there is any text
  671.    if(szBuf[0] != 0)
  672.       ::EnableWindow(GetDlgItem(IDC_BTN_SUGGEST)->GetSafeHwnd(), TRUE);
  673.    else
  674.       ::EnableWindow(GetDlgItem(IDC_BTN_SUGGEST)->GetSafeHwnd(), FALSE);
  675. }
  676.  
  677.  
  678. void TSpellDlg::CmIgnore()
  679. {
  680.    GoToNextWord();
  681. }
  682.  
  683.  
  684. void TSpellDlg::CmIgnoreAll()
  685. {
  686.    char szWordNotInDic[64];
  687.  
  688.    GetDlgItemText(IDC_NOT_IN_DIC, szWordNotInDic, sizeof(szWordNotInDic)-1);
  689.    if(szWordNotInDic[0] != 0)
  690.    {
  691.       m_pSpellDocument->m_pSpellChecker->AddToIgnoreAll(szWordNotInDic);
  692.  
  693.       //going to next word
  694.       GoToNextWord();
  695.    }
  696. }
  697.  
  698.  
  699. void TSpellDlg::CmChange()
  700. {
  701.    // Replacing word which doesn't exist in dictionary with suggested word
  702.    // in text box suggest (if there is any) and going on with finding
  703.    // words in text.
  704.  
  705.    char szSuggWord[32];
  706.  
  707.    GetDlgItemText(IDC_COMBO_SUGGEST, szSuggWord, sizeof(szSuggWord)-1);
  708.    if(szSuggWord[0] != 0)
  709.     {
  710.       m_pSpellDocument->ReplaceWord(szSuggWord);
  711.       GoToNextWord();
  712.    }
  713. }
  714.  
  715.  
  716. void TSpellDlg::CmChangeAll()
  717. {
  718.    // Replacing word which doesn't exist in dictionary with suggested word
  719.    // in text box suggest
  720.    // This is done automaticly every time when this word occures.
  721.    // This is done only while we are in this dialog (i.e. in this session)
  722.  
  723.    char  szSuggWord[64];
  724.    char  szWordNotInDic[64];
  725.  
  726.    GetDlgItemText(IDC_COMBO_SUGGEST, szSuggWord,     sizeof(szSuggWord)-1);
  727.    GetDlgItemText(IDC_NOT_IN_DIC,    szWordNotInDic, sizeof(szWordNotInDic)-1);
  728.  
  729.    if(szWordNotInDic[0] != 0) {
  730.       m_pSpellDocument->m_pSpellChecker->AddToChangeAll(szWordNotInDic, szSuggWord);
  731.    }
  732.  
  733.    if(szSuggWord[0] != 0) {
  734.       m_pSpellDocument->ReplaceWord(szSuggWord);
  735.    }
  736.    GoToNextWord();
  737. }
  738.  
  739.  
  740. void TSpellDlg::CmAdd()
  741. {
  742.    // Adds word (that we haven't found in dictionary) in custom dictionary
  743.  
  744.    char szWordNotInDic[32];
  745.  
  746.    GetDlgItemText(IDC_NOT_IN_DIC, szWordNotInDic, sizeof(szWordNotInDic)-1);
  747.    if(szWordNotInDic[0] != 0)
  748.    {
  749.       m_pSpellDocument->m_pSpellChecker->AddWord(szWordNotInDic);
  750.  
  751.       //going to next word
  752.       GoToNextWord();
  753.    }
  754. }
  755.  
  756.  
  757. void TSpellDlg::CmSuggest()
  758. {
  759.    char szSuggWord[32];
  760.  
  761.    GetDlgItemText(IDC_COMBO_SUGGEST, szSuggWord, sizeof(szSuggWord)-1);
  762.  
  763.    if(szSuggWord[0] != 0)
  764.     {
  765.       SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_RESETCONTENT, 0, 0L);
  766.       // List of suggestions for word which has not been found is
  767.       // being filled now
  768.  
  769.       BOOL fSuggestions = FALSE;
  770.  
  771.         // List of suggestions for word which has not been found is
  772.       // being filled now
  773.       for(int i = 0; i < 10; i++)
  774.       {
  775.          CString strSuggestion = m_pSpellDocument->m_pSpellChecker->GetSuggestion(m_pSpellDocument->m_szString, i);
  776.  
  777.          if(strSuggestion.GetLength() > 0)
  778.          {
  779.             SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)(LPCTSTR)strSuggestion);
  780.             fSuggestions = TRUE;
  781.          }
  782.          else
  783.             break;
  784.       }
  785.       if(fSuggestions)
  786.       {
  787.            SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_SETCURSEL, 0, 0);
  788.       }
  789.       else
  790.       {
  791.          char szBuf[40];
  792.  
  793.          LoadString(AfxGetResourceHandle(), IDS_WE_SPELL_NOSUGGESTION, szBuf, sizeof(szBuf));
  794.          SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)szBuf);
  795.       }
  796.  
  797.         ::EnableWindow(GetDlgItem(IDC_BTN_SUGGEST)->GetSafeHwnd(), FALSE);
  798.    }
  799. }
  800.  
  801.  
  802. void TSpellDlg::CmOptions()
  803. {
  804.    TSpellOptionsDynamicDlg(this, m_pSpellDocument).DoModal();
  805. }
  806.  
  807. void TSpellDlg::GoToNextWord()
  808. {
  809.    HCURSOR hcurSave = ::SetCursor(LoadCursor(NULL, IDC_WAIT));
  810.  
  811.    // we reject offered suggestion for a found word and we search for a next
  812.    // word which is not in dictionary
  813.  
  814.    if(m_pSpellDocument->FindNextNotExistWord() == TRUE)
  815.    {
  816.       // Restore the previous cursor.
  817.       ::SetCursor(hcurSave);
  818.  
  819.       // word which hasn't been found in dictionary is being set
  820.       // in tekstBox IDC_NOT_IN_DIC
  821.       SetDlgItemText(IDC_NOT_IN_DIC, m_pSpellDocument->m_szString);
  822.       // We have found word which doesn't exist in dictionary.
  823.       // Lets select it now.
  824.       m_pSpellDocument->SelectNotExistSpellWord();
  825.  
  826.       if(m_pSpellDocument->m_pSpellChecker->GetAlwaysSuggest())
  827.       {
  828.          BOOL fSuggestions = FALSE;
  829.  
  830.          // List of suggestions for word which has not been found is
  831.          // being filled now
  832.          SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_RESETCONTENT, 0, 0L);
  833.          for(int i = 0; i < 10; i++)
  834.          {
  835.             CString strSuggestion = m_pSpellDocument->m_pSpellChecker->GetSuggestion(m_pSpellDocument->m_szString, i);
  836.  
  837.             if(strSuggestion.GetLength() > 0)
  838.             {
  839.                SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)(LPCTSTR)strSuggestion);
  840.                fSuggestions = TRUE;
  841.             }
  842.             else
  843.                break;
  844.          }
  845.          if(fSuggestions)
  846.          {
  847.             SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_SETCURSEL, 0, 0);
  848.          }
  849.          else
  850.          {
  851.             char szBuf[40];
  852.  
  853.             LoadString(AfxGetResourceHandle(), IDS_WE_SPELL_NOSUGGESTION, szBuf, sizeof(szBuf));
  854.             SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)szBuf);
  855.          }
  856.          ::EnableWindow(GetDlgItem(IDC_BTN_SUGGEST)->GetSafeHwnd(), FALSE);
  857.       }
  858.       else
  859.       {
  860.          SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_RESETCONTENT, 0, 0L);
  861.          SendDlgItemMessage(IDC_COMBO_SUGGEST, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)"");
  862.          ::EnableWindow(GetDlgItem(IDC_BTN_SUGGEST)->GetSafeHwnd(), FALSE);
  863.       }
  864.    }
  865.    else
  866.    {
  867.       // There are no more words in document which do not
  868.       // exist in dictionary
  869.  
  870.       // Restore the previous cursor.
  871.       ::SetCursor(hcurSave);
  872.       EndDialog(IDOK);
  873.    }
  874. }
  875.  
  876. #undef IDC_NOT_IN_DIC
  877. #undef IDC_COMB_SUGGEST
  878. #undef IDC_BTN_IGNOR
  879. #undef IDC_BTN_IGNORALL
  880. #undef IDC_BTN_CHANGE
  881. #undef IDC_BTN_CHANGEALL
  882. #undef IDC_BTN_SUGGEST
  883. #undef IDC_BTN_ADD
  884. #undef IDC_BTN_OPTIONS
  885.  
  886.  
  887.  
  888. /*******************************************************************
  889.                    TSpellOptionsDynamicDlg
  890.  
  891.   Dialog for dinamic change of options while spelling
  892. *******************************************************************/
  893.  
  894. #define IDC_CHECK_ALWAYSSUGGEST   101
  895. #define IDC_CHECK_IGNOREUPPERCASE 102
  896. #define IDC_CHECK_IGNORENUMBERS   103
  897.  
  898.  
  899. BEGIN_MESSAGE_MAP(TSpellOptionsDynamicDlg, CDialog)
  900.    ON_BN_CLICKED(IDOK, OnOK)
  901. END_MESSAGE_MAP()
  902.  
  903.  
  904. TSpellOptionsDynamicDlg::TSpellOptionsDynamicDlg(CWnd * pParent, TSpellText *pSpellDoc)
  905.    : CDialog("SpellOptions_Dynamic", pParent)
  906. {
  907.    m_pSpellDocument = pSpellDoc;
  908. }
  909.  
  910.  
  911. BOOL TSpellOptionsDynamicDlg::OnInitDialog()
  912. {
  913.    CDialog::OnInitDialog();
  914.    //CenterDialog(HWindow, TRUE);
  915.  
  916.    CheckDlgButton(IDC_CHECK_ALWAYSSUGGEST,   m_pSpellDocument->m_pSpellChecker->GetAlwaysSuggest());
  917.    CheckDlgButton(IDC_CHECK_IGNOREUPPERCASE, m_pSpellDocument->m_pSpellChecker->GetIgnoreWordsInUppercase());
  918.    CheckDlgButton(IDC_CHECK_IGNORENUMBERS,   m_pSpellDocument->m_pSpellChecker->GetIgnoreWordsWithNumbers());
  919.  
  920.    return TRUE;
  921. }
  922.  
  923. void TSpellOptionsDynamicDlg::OnOK()
  924. {
  925.    m_pSpellDocument->m_pSpellChecker->SetAlwaysSuggest(IsDlgButtonChecked(IDC_CHECK_ALWAYSSUGGEST));
  926.    m_pSpellDocument->m_pSpellChecker->SetIgnoreWordsInUppercase(IsDlgButtonChecked(IDC_CHECK_IGNOREUPPERCASE));
  927.    m_pSpellDocument->m_pSpellChecker->SetIgnoreWordsWithNumbers(IsDlgButtonChecked(IDC_CHECK_IGNORENUMBERS));
  928.    EndDialog(IDOK);
  929. }
  930.  
  931. #undef IDC_CHECK_ALWAYSSUGGEST
  932. #undef IDC_CHECK_IGNOREUPPERCASE
  933. #undef IDC_CHECK_IGNORENUMBERS
  934.  
  935.